package com.third.config;

import com.third.entity.RestBean;
import com.third.entity.Users;
import com.third.entity.vo.respone.AuthorizeVO;
import com.third.filter.JwtAuthorizeFilter;
import com.third.mapper.UsersMapper;
import com.third.service.UsersService;
import com.third.utils.JwtUtils;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * @author 唐博文
 * @version 2023.1.2
 * @date 2023/10/24 16:24 星期二
 */
@Configuration
public class SecurityConfiguration {
    
    @Resource
    JwtUtils utils;
    @Resource
    JwtAuthorizeFilter jwtAuthorizeFilter;
    @Resource
    UsersService service;
    @Resource
    UsersMapper mapper;
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        return http
                .authorizeHttpRequests(auth->{
                    auth.requestMatchers(new AntPathRequestMatcher("/api/auth/**")
                            ,new AntPathRequestMatcher("/error")
                            ,new AntPathRequestMatcher("/out/**")
                            ,new AntPathRequestMatcher("/inBound/**")
                            ,new AntPathRequestMatcher("/super/**")
                            ,new AntPathRequestMatcher("/LoginApp/**")
                            ,new AntPathRequestMatcher("/user/**")
                            ,new AntPathRequestMatcher("/brand/**")


                    ).permitAll();
                    auth.anyRequest().authenticated();
                })
                .formLogin(conf->{
                    conf.loginProcessingUrl("/api/auth/login");
                    //登陆成功后执行的方法
                    conf.successHandler(this::onAuthenticationSuccess);
                    conf.failureHandler(this::onAuthenticationFailure);
                })//退出登录
                .logout(conf->{
                    conf.logoutUrl("/api/auth/logout");
                    conf.logoutSuccessHandler(this::onLogoutSuccess);
                })
                //处理没有登录的
                .exceptionHandling(conf->{
                    conf.authenticationEntryPoint(this::onUnauthorized);
                    //登录了没有权限
                    conf.accessDeniedHandler(this::onAccessDeny);
                })
                .csrf(AbstractHttpConfigurer::disable)
                .sessionManagement(conf->{
                    //制定了会话策略为无状态
                    conf.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
                })
                .addFilterBefore(jwtAuthorizeFilter, UsernamePasswordAuthenticationFilter.class)
                .build();
    }
    
    private void onAccessDeny(HttpServletRequest request,
                              HttpServletResponse response,
                              AccessDeniedException e)throws IOException {
        response.setContentType("application/json;charset");
        response.getWriter().write(RestBean.unauthorized(e.getMessage()).asJsonString());
    }
    
    private void onUnauthorized(HttpServletRequest request,
                                HttpServletResponse response,
                                AuthenticationException exception) throws IOException {
        response.setContentType("application/json;charset=utf-8");
        response.getWriter().write(RestBean.unauthorized(exception.getMessage()).asJsonString());
    }
    
    
    //登陆成功
    public void onAuthenticationSuccess(HttpServletRequest request,
                                        HttpServletResponse response,
                                        Authentication authentication) throws IOException{
        response.setContentType("application/json;charset=utf-8");
        User user=(User) authentication.getPrincipal();
        System.out.println("Authorities:::"+user.getAuthorities());
        Users users = service.findUsersByNameOrEmail(user.getUsername());
        System.out.println("user::::"+users);
        String token = utils.createJwt(user, users.getUserId(), user.getUsername());
        String RoleName= mapper.findRoleNameByUsers(users.getRoleId());
        AuthorizeVO vo=users.asViewObject(AuthorizeVO.class,v->{
            v.setExpire(utils.expireTime());
            v.setToken(token);
            v.setRole(RoleName);
        });
        response.getWriter().write(RestBean.success(vo).asJsonString());
    }
    
    
    //登陆失败
    public void onAuthenticationFailure(HttpServletRequest request, 
                                        HttpServletResponse response, 
                                        AuthenticationException exception) throws IOException{
        response.setContentType("application/json;charset=utf-8");
        response.getWriter().write(RestBean.unauthorized(exception.getMessage()).asJsonString());
    }
    
    
    //退出登录
    public void onLogoutSuccess(HttpServletRequest request,
                                HttpServletResponse response,
                                Authentication authentication) throws IOException{
        response.setContentType("application/json;charset=utf-8");
        PrintWriter writer=response.getWriter();
        String authorization = request.getHeader("Authorization");
        if(utils.invalidateJwt(authorization)){
            writer.write(RestBean.success().asJsonString());
        }else {
            writer.write(RestBean.failure(400,"退出登陆失败").asJsonString());
        }
    }
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
}
